
#include <BOpenGL>
#include <BPainter>
#include <BEvent>
#include <BSystem>
#include "member_BWidget.h"
#include "member_BPixmap.h"
#include "member_BImage.h"
#include "member_BTexture.h"

#ifdef linux

#include <X11/cursorfont.h>

#endif

using namespace BWE;

extern BArray<GLuint>		UnusedTextureObjects;
extern BArray<GLuint>		UnusedFrameBufferObjects;
extern BArray<GLuint>		UnusedRenderBufferObjects;

member_BPixmap::member_BPixmap(BPixmap* pixmap)
{
	boss = pixmap;
	samples = 4;
	fbo = 0;
	rbo= 0;
	msfbo = 0;
	msrbo = 0;
	mstbo = 0;
	drag = 0;
	hoverWidget = 0;
	focusWidget = 0;
}
member_BPixmap::~member_BPixmap()
{

}

bool member_BPixmap::check() const
{
	GLenum state = glCheckFramebufferStatus(GL_FRAMEBUFFER);
	switch (state)
	{
	case GL_FRAMEBUFFER_COMPLETE:
		return true;
	case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
		puts("FBO Initialization Failed : incomplete attachment");
		return false;
	case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
		puts("FBO Initialization Failed : missing attachment");
		return false;
	case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
		puts("FBO Initialization Failed : draw buffer is invalid");
		return false;
	case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
		puts("FBO Initialization Failed : read buffer is invalid");
		return false;
	case GL_FRAMEBUFFER_UNSUPPORTED:
		puts("FBO Initialization Failed : this is not supported");
		return false;
	}

	return 0 != glIsFramebuffer(fbo);
}

void member_BPixmap::update(const BEvent& event)
{
	for (int i = widgets.size() - 1; i >= 0; i--)
	{
		BWidget* rootWidget = widgets[i];
		updateWidget(rootWidget, event);
	}
	if (tipsBoard.update())
	{
		refresh = true;
		boss->dirty();
	}
}
void member_BPixmap::fresh()
{
	BEvent event(Event_Fresh);
	for (int i = widgets.size() - 1; i >= 0; i--)
	{
		BWidget* rootWidget = widgets[i];
		freshWidget(rootWidget, event);
	}
	if (refresh)
	{
		boss->dirty();
	}
}
void member_BPixmap::frame()
{
	BSize msize = size;
	for (int i = 0; i < widgets.size(); i++)
	{
		BWidget* widget = widgets[i];
		if (msize.width() < widget->width())
			msize.width() = widget->width();
		if (msize.height() < widget->height())
			msize.height() = widget->height();
	}
	if (size != msize)
	{
		size = msize;
		resized = true;
	}
	if (fbo == 0 || rbo == 0)
		resized = true;
	if (resized)
	{
		GLint backup_frame_buffer;
		glGetIntegerv(GL_FRAMEBUFFER_BINDING, &backup_frame_buffer);
		if (samples > 0)
		{
			if (!msfbo)
			{
				glGenFramebuffers(1, &msfbo);
				glGenRenderbuffers(1, &msrbo);
				glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
				glGenTextures(1, &mstbo);
			}
			if (msfbo && mstbo)
			{
				glBindFramebuffer(GL_FRAMEBUFFER, msfbo);

				glBindRenderbuffer(GL_RENDERBUFFER, msrbo);
				glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_DEPTH24_STENCIL8, size.width(), size.height());
				glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, msrbo);

				glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mstbo);
				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
				glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA, size.width(), size.height(), GL_TRUE);
				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT5, GL_TEXTURE_2D_MULTISAMPLE, mstbo, 0);
			}
		}
		else
		{
			if (msfbo)
			{
				UnusedFrameBufferObjects.append(msfbo);
				msfbo = 0;
			}
			if (msrbo)
			{
				UnusedRenderBufferObjects.append(msrbo);
				msrbo = 0;
			}
			if (mstbo)
			{
				UnusedTextureObjects.append(mstbo);
				mstbo = 0;
			}
		}
		if (!fbo)
		{
			glGenFramebuffers(1, &fbo);
			glGenRenderbuffers(1, &rbo);
		}
		if (fbo)
		{
			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
			glBindRenderbuffer(GL_RENDERBUFFER, rbo);
			glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, size.width(), size.height());
			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
		}
		if (GLuint tbo = texture_member(boss)->tbo)
		{
			glBindTexture(GL_TEXTURE_2D, tbo);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_2D, tbo, 0);
		}
		glBindFramebuffer(GL_FRAMEBUFFER, backup_frame_buffer);
		resized = false;
	}
	if (fbo)
	{
		state.save();
		for (int i = 0; i < widgets.size(); i++)
		{
			BWidget* rootWidget = widgets[i];
			frameWidget(rootWidget);
		}
		state.open();

		state.save();
		if (msfbo)
		{
			glBindFramebuffer(GL_FRAMEBUFFER, msfbo);
			glDrawBuffer(GL_COLOR_ATTACHMENT5);
			glReadBuffer(GL_COLOR_ATTACHMENT5);
		}
		else
		{
			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
			glDrawBuffer(GL_COLOR_ATTACHMENT4);
			glReadBuffer(GL_COLOR_ATTACHMENT4);
		}

		glClearColor(color.r() / 255.0f, color.g() / 255.0f, color.b() / 255.0f, color.a() / 255.0f);
		glClear(GL_COLOR_BUFFER_BIT);
		
		glDisable(GL_LIGHTING);
		glDisable(GL_DEPTH_TEST);
		glDisable(GL_CULL_FACE);
		
		glViewport(0, 0, size.width(), size.height());

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(0, size.width(), size.height(), 0, -1, 1);

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();

		glEnable(GL_TEXTURE_2D);
		BRect clip = size;
		for (int i = 0; i < widgets.size(); i++)
		{
			BWidget* rootWidget = widgets[i];
			drawWidget(rootWidget, clip, rootWidget->pos(), size.height());
		}
		for (int i = 0; i < popupWidgets.size(); i++)
		{
			BWidget* widget = popupWidgets[i];
			drawPopupWidget(widget, clip, widget->globalPos(), size.height());
		}
		glBindTexture(GL_TEXTURE_2D, 0);
		glDisable(GL_TEXTURE_2D);

		boss->paint();
		if (msfbo)
		{
			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
			glDrawBuffer(GL_COLOR_ATTACHMENT4);
			glReadBuffer(GL_COLOR_ATTACHMENT4);
			glBindFramebuffer(GL_READ_FRAMEBUFFER, msfbo);
			glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
			glBlitFramebuffer(0, 0, size.width(), size.height(), 0, 0, size.width(), size.height(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
		}
		boss->emit(Signal_Framed);
		state.open();
	}
}
void member_BPixmap::updateWidget(BWidget* widget, const BEvent& event)
{
	if (widget && widget->enabled())
	{
		widget_member(widget)->procEvent(event);
		for (int i = 0; i < widget->childCount(); i++)
		{
			BWidget* child = widget->child(i);
			updateWidget(child, event);
		}
	}
}
void member_BPixmap::freshWidget(BWidget* widget, const BEvent& event)
{
	if (widget == 0 || !widget_member(widget)->visible)
		return;
	if (widget_member(widget)->ignored())
		return;
	if (widget_member(widget)->refresh)
	{
		widget_member(widget)->refresh = false;
		widget_member(widget)->procEvent(event);
		widget_member(widget)->dirty = true;
		refresh = true;
	}
	if (widget_member(widget)->dirtyLayouts)
	{
		widget_member(widget)->dirtyLayouts = false;
		widget_member(widget)->adjustDirtyLayouts();
	}
	for (int i = 0; i < widget->childCount(); i++)
	{
		BWidget* child = widget->child(i);
		freshWidget(child, event);
	}
}

bool member_BPixmap::hover(BWidget* widget)
{
	if (hoverWidget != widget)
	{
		hoverWidget = widget;
		if (widget)
			widget->fresh();
	}
	return true;
}
bool member_BPixmap::focus(BWidget* widget)
{
	if (focusWidget != widget)
	{
		if (focusWidget)
		{
			widget_member(focusWidget)->focused = false;
			BEvent focusEvent(Event_Focus);
			focusEvent.setValue(false);
			widget_member(focusWidget)->procEvent(focusEvent);
			focusWidget = 0;
		}
		if (widget && widget->enabled())
		{
			widget_member(widget)->focused = true;
			BEvent focusEvent(Event_Focus);
			focusEvent.setValue(true);
			widget_member(widget)->procEvent(focusEvent);
			focusWidget = widget;

			if (popupWidgets.contain(focusWidget) && popupWidgets.last() != focusWidget)
			{
				popupWidgets.remove(focusWidget);
				popupWidgets.append(focusWidget);
			}
			focusWidget->fresh();
		}
		return true;
	}
	return false;
}
bool member_BPixmap::popup(BWidget* widget, bool flag)
{
	if (flag)
	{
		if (!popupWidgets.contain(widget))
		{
			popupWidgets.append(widget);
			BEvent popupEvent(Event_Popup, true);
			widget_member(widget)->procEvent(popupEvent);
			return true;
		}
	}
	else if (popupWidgets.remove(widget))
	{
		BEvent popupEvent(Event_Popup, false);
		widget_member(widget)->procEvent(popupEvent);
		for (int i = 0; i < popupWidgets.size(); i++)
		{
			BWidget* pwidget = popupWidgets[i];
			if (pwidget->under(widget))
			{
				if (focusWidget == pwidget)
					focus(0);
				popupWidgets.remove(i--);
				widget_member(widget)->procEvent(popupEvent);
			}
		}
		refresh = true;
		return true;
	}
	return false;
}

BWidget* member_BPixmap::widgetUnderPoint(const BPoint& point)
{
	for (int i = popupWidgets.size() - 1; i >= 0; i--)
	{
		BWidget* popupWidget = popupWidgets[i];
		if (!popupWidget->visible())
			continue;
		BWidget* widget = findPopupWidget(popupWidget, point, size);
		if (widget)
			return widget;
		if (popupWidget->modal())
			return 0;
	}
	for (int i = widgets.size() - 1; i >= 0; i--)
	{
		BWidget* rootWidget = widgets[i];
		if (!rootWidget->visible())
			continue;
		BWidget* widget = findWidget(rootWidget, point, size);
		if (widget)
			return widget;
	}
	return 0;
}
BWidget* member_BPixmap::findWidget(BWidget* widget, const BPoint& point, const BRect& clip)
{
	BRect rect = widget->rect();
	BRect clipRect = rect & clip;
	if (!clipRect.contain(point))
		return 0;
	currentRect = clipRect;
	BPoint localPoint = point - rect.pos();
	for (int i = widget_member(widget)->children.size() - 1; i >= 0; i--)
	{
		BWidget* child = widget_member(widget)->children[i];
		if (!child->visible())
			continue;
		if (child->floating())
		{
			BWidget* ret = findWidget(child, localPoint, widget->size());
			if (ret)
				return ret;
			continue;
		}
		const BRect& centerRect = widget->centerRect();
		const BRect& leftRect = widget->rect(Part_Left);
		const BRect& topRect = widget->rect(Part_Top);
		const BRect& rightRect = widget->rect(Part_Right);
		const BRect& bottomRect = widget->rect(Part_Bottom);
		BRect childRect = child->rect();
		if (centerRect.intersect(childRect))
		{
			BWidget* ret = findWidget(child, localPoint, centerRect);
			if (ret)
				return ret;
		}
		if (topRect.intersect(childRect))
		{
			BWidget* ret = findWidget(child, localPoint, topRect);
			if (ret)
				return ret;
		}
		if (leftRect.intersect(childRect))
		{
			BWidget* ret = findWidget(child, localPoint, leftRect);
			if (ret)
				return ret;
		}
		if (rightRect.intersect(childRect))
		{
			BWidget* ret = findWidget(child, localPoint, rightRect);
			if (ret)
				return ret;
		}
		if (bottomRect.intersect(childRect))
		{
			BWidget* ret = findWidget(child, localPoint, bottomRect);
			if (ret)
				return ret;
		}
	}
	return widget;
}
BWidget* member_BPixmap::findPopupWidget(BWidget* widget, const BPoint& point, const BRect& clip)
{
	if (!widget->enabled())
		return 0;

	BRect rect = widget->rect();

	BRect viewRect = widget->absoluteRect() & clip;
	if (!viewRect.contain(point))
		return 0;

	BWidgetHolderArray& children = widget_member(widget)->children;
	for (int i = children.size() - 1; i >= 0; i--)
	{
		BWidget* child = widget->child(i);
		if (!child->visible())
			continue;

		if (widget_member(child)->floating)
		{
			BWidget* ret = findPopupWidget(child, point, viewRect);
			if (ret)
				return ret;
		}
		else
		{
			BRect clientViewRect = widget->centerRect();
			clientViewRect += viewRect.pos();
			BWidget* ret = findPopupWidget(child, point, clientViewRect);
			if (ret)
				return ret;
		}
	}

	return widget;
}

void member_BPixmap::frameWidget(BWidget* widget)
{
	if (!widget_member(widget)->visible)
		return;
	if (!widget_member(widget)->state.shown)
		return;
	BWidgetHolderArray& children = widget_member(widget)->children;
	for (int i = 0; i < children.size(); i++)
	{
		BWidget* child = children[i];
		frameWidget(child);
	}
	if (widget_member(widget)->dirty)
	{
		widget_member(widget)->frame(msfbo, GL_COLOR_ATTACHMENT5);
	}
}
void member_BPixmap::drawWidget(BWidget* widget, const BRect& clip, const BPoint& offset, int frameHeight)
{
	if (!widget_member(widget)->visible || popupWidgets.contain(widget))
		return;

	BSize size = widget->size();
	BRect ab_rect(offset, size);
	BRect view = ab_rect & clip;
	if (view.empty())
		return;

	glViewport(view.x(), frameHeight - view.bottom(), view.width(), view.height());

	BRect area(view.pos() - ab_rect.pos(), view.size());
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(area.left(), area.right(), area.bottom(), area.top(), -1, 1);

	if (widget_member(widget)->tbo)
	{
		int width = widget_member(widget)->size.width();
		int height = widget_member(widget)->size.height();
		glColor4ub(255, 255, 255, widget_member(widget)->opacity);
		glBindTexture(GL_TEXTURE_2D, widget_member(widget)->tbo);
		glBegin(GL_QUADS);
		glTexCoord2f(0.0f, 1.0f);		glVertex2i(0, 0);
		glTexCoord2f(0.0f, 0.0f);		glVertex2i(0, height);
		glTexCoord2f(1.0f, 0.0f);		glVertex2i(width, height);
		glTexCoord2f(1.0f, 1.0f);		glVertex2i(width, 0);
		glEnd();
	}
	if (!widget_member(widget)->layered)
	{
		BWidgetHolderArray& children = widget_member(widget)->children;
		for (int i = 0; i < children.size(); i++)
		{
			BWidget* child = children[i];
			drawWidget(child, view, offset + child->pos(), frameHeight);
		}
	}
	if (!widget_member(widget)->layered)
	{
		BRect ab_crect = widget->centerRect() + offset;
		BRect cview = ab_crect & clip;
		BWidgetHolderArray& children = widget_member(widget)->children;
		for (int i = 0; i < children.size(); i++)
		{
			BWidget* child = children[i];
			if (!widget_member(child)->visible)
				continue;
			if (widget_member(child)->ignored())
				continue;
			if (widget_member(child)->floating)
				drawWidget(child, view, offset + child->pos(), frameHeight);
			else
				drawWidget(child, cview, offset + child->pos(), frameHeight);
		}
	}
}
void member_BPixmap::drawPopupWidget(BWidget* widget, const BRect& clip, const BPoint& offset, int frameHeight)
{
	if (!widget_member(widget)->visible)
		return;
	BSize size = widget->size();
	BRect ab_rect(offset, size);
	BRect view = ab_rect & clip;
	if (view.empty())
		return;
	glViewport(view.x(), frameHeight - view.bottom(), view.width(), view.height());

	BRect area(view.pos() - ab_rect.pos(), view.size());
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(area.left(), area.right(), area.bottom(), area.top(), -1, 1);

	if (widget_member(widget)->tbo)
	{
		int width = widget_member(widget)->size.width();
		int height = widget_member(widget)->size.height();
		glColor4ub(255, 255, 255, widget_member(widget)->opacity);
		glBindTexture(GL_TEXTURE_2D, widget_member(widget)->tbo);
		glBegin(GL_QUADS);
		glTexCoord2f(0.0f, 1.0f);		glVertex2i(0, 0);
		glTexCoord2f(0.0f, 0.0f);		glVertex2i(0, height);
		glTexCoord2f(1.0f, 0.0f);		glVertex2i(width, height);
		glTexCoord2f(1.0f, 1.0f);		glVertex2i(width, 0);
		glEnd();
	}
	if (!widget_member(widget)->layered)
	{
		BWidgetHolderArray& children = widget_member(widget)->children;
		for (int i = 0; i < children.size(); i++)
		{
			BWidget* child = children[i];
			drawWidget(child, view, offset + child->pos(), frameHeight);
		}
	}
}
void member_BPixmap::drawCursor(BPainter& painter)
{
	if (!hoverWidget)
		return;
	BPoint point = cursorPos;

	BCursor* cursor = hoverWidget->cursor();
	if (cursor && cursor->type() == Cursor_None)
	{
		BPoint origin = cursor->point();
		BSize size = cursor->size();
		int x = point.x() - origin.x();
		int y = point.y() - origin.y();
		int w = size.width();
		int h = size.height();

		BImage* image = cursor->image();
		if (image)
		{
			painter.setColor(255, 255, 255);
			painter.drawPoint(point);
			painter.drawImage(x, y, w, h, image);
		}
	}
}
void member_BPixmap::drawDrag(BPainter& painter)
{
	if (!drag)
		return;
	BPoint point = cursorPos;
	BPoint origin;
	BSize size(100, 100);
	int x = point.x() - origin.x();
	int y = point.y() - origin.y();
	int w = size.width();
	int h = size.height();

	BImage* image = drag->image();
	if (image)
	{
		painter.setColor(255, 255, 255);
		painter.drawPoint(point);
		painter.drawImage(x, y, w, h, image);
	}
}
void member_BPixmap::drawTips(BPainter& painter)
{
	if (tipsBoard.visible)
	{
		if (tipsBoard.dirty)
		{
			tipsBoard.fresh();
		}

		glEnable(GL_TEXTURE_2D);
		const BRect& area = tipsBoard.area;
		glColor4ub(255, 255, 255, 255);
		glBindTexture(GL_TEXTURE_2D, tipsBoard.tbo);
		glBegin(GL_QUADS);
		glTexCoord2f(0.0f, 1.0f);		glVertex2i(area.left(), area.top());
		glTexCoord2f(0.0f, 0.0f);		glVertex2i(area.left(), area.bottom());
		glTexCoord2f(1.0f, 0.0f);		glVertex2i(area.right(), area.bottom());
		glTexCoord2f(1.0f, 1.0f);		glVertex2i(area.right(), area.top());
		glEnd();
		glBindTexture(GL_TEXTURE_2D, 0);
		glDisable(GL_TEXTURE_2D);
	}
}
void member_BPixmap::freshCursor()
{
	BImage* image = 0;
	CursorType type = Cursor_None;
	if (hoverCursor)
	{
		type = hoverCursor->type();
		image = hoverCursor->image(type);
	}

#ifdef linux
	if (image)
	{
		return;
	}
	if (hoverCursor)
		type = hoverCursor->type();
	unsigned int font_cursor_type = 0;
	switch (type)
	{
	case Cursor_None:
	case Cursor_Arrow:
		font_cursor_type = XC_arrow;
		break;
	case Cursor_Ibeam:
		font_cursor_type = XC_xterm;
		break;
	case Cursor_Cross:
		font_cursor_type = XC_X_cursor;
		break;
	case Cursor_Wait:
		font_cursor_type = XC_watch;
		break;
	case Cursor_Forbidden:
		font_cursor_type = XC_X_cursor;
		break;
	case Cursor_Hand:
		font_cursor_type = XC_hand2;
		break;
	case Cursor_Help:
		font_cursor_type = XC_question_arrow;
		break;
	case Cursor_UpArrow:
		font_cursor_type = XC_sb_up_arrow;
		break;
	case Cursor_SizeTop:
		font_cursor_type = XC_top_side;
		break;
	case Cursor_SizeLeft:
		font_cursor_type = XC_left_side;
		break;
	case Cursor_SizeRight:
		font_cursor_type = XC_right_side;
		break;
	case Cursor_SizeBottom:
		font_cursor_type = XC_bottom_side;
		break;
	case Cursor_SizeVer:
		font_cursor_type = XC_sb_v_double_arrow;
		break;
	case Cursor_SizeHor:
		font_cursor_type = XC_sb_h_double_arrow;
		break;
	case Cursor_SizeLeftTop:
		font_cursor_type = XC_top_left_corner;
		break;
	case Cursor_SizeRightBottom:
		font_cursor_type = XC_bottom_right_corner;
		break;
	case Cursor_SizeLeftBottom:
		font_cursor_type = XC_bottom_left_corner;
		break;
	case Cursor_SizeRightTop:
		font_cursor_type = XC_top_right_corner;
		break;
	case Cursor_SizeAll:
		font_cursor_type = XC_fleur;
		break;
	default:
		break;
	}
	//if (fontCursors[font_cursor_type] == 0)
	//{
	//	fontCursors[font_cursor_type] = XCreateFontCursor(display, font_cursor_type);
	//}
#endif

#ifdef _WIN32
	if (image)
	{
		while (ShowCursor(FALSE) >= 0)
			ShowCursor(FALSE);
		return;
	}
	while (ShowCursor(TRUE) < 0)
		ShowCursor(TRUE);
	switch (type)
	{
	case Cursor_None:
	case Cursor_Arrow:
		SetCursor(LoadCursor(0, IDC_ARROW));
		break;
	case Cursor_Ibeam:
		SetCursor(LoadCursor(0, IDC_IBEAM));
		break;
	case Cursor_Cross:
		SetCursor(LoadCursor(0, IDC_CROSS));
		break;
	case Cursor_Wait:
		SetCursor(LoadCursor(0, IDC_WAIT));
		break;
	case Cursor_Forbidden:
		SetCursor(LoadCursor(0, IDC_NO));
		break;
	case Cursor_Hand:
		SetCursor(LoadCursor(0, IDC_HAND));
		break;
	case Cursor_Help:
		SetCursor(LoadCursor(0, IDC_HELP));
		break;
	case Cursor_SizeVer:
	case Cursor_SizeTop:
	case Cursor_SizeBottom:
		SetCursor(LoadCursor(0, IDC_SIZENS));
		break;
	case Cursor_SizeHor:
	case Cursor_SizeLeft:
	case Cursor_SizeRight:
		SetCursor(LoadCursor(0, IDC_SIZEWE));
		break;
	case Cursor_SizeLeftTop:
	case Cursor_SizeRightBottom:
		SetCursor(LoadCursor(0, IDC_SIZENWSE));
		break;
	case Cursor_SizeLeftBottom:
	case Cursor_SizeRightTop:
		SetCursor(LoadCursor(0, IDC_SIZENESW));
		break;
	case Cursor_SizeAll:
		SetCursor(LoadCursor(0, IDC_SIZEALL));
		break;
	case Cursor_UpArrow:
		SetCursor(LoadCursor(0, IDC_UPARROW));
		break;
	default:
		break;
	}
#endif

}

void member_BPixmap::procMousePress(BMouseEvent& mouseEvent)
{
	mouse_pressed = true;
	mouse_pressed_time = mouseEvent.time();
	mouse_pressed_pos = mouseEvent.globalPos();

	BWidget* widget = widgetUnderPoint(mouse_pressed_pos);
	this->focus(widget);
	if (focusWidget)
	{
		mouseEvent.setPos(mouseEvent.absolutePos() - focusWidget->globalPos());
		widget_member(focusWidget)->procEvent(mouseEvent);
	}
}
void member_BPixmap::procMouseRelease(BMouseEvent& mouseEvent)
{
	mouse_pressed = false;

	if (focusWidget)
	{
		mouseEvent.setPos(mouseEvent.absolutePos() - focusWidget->globalPos());
		widget_member(focusWidget)->procEvent(mouseEvent);
	}
	if (focusWidget)
	{
		int distance = (mouseEvent.absolutePos() - mouse_pressed_pos).length();
		BReal time = mouseEvent.time();
		BReal interval = time - mouse_pressed_time;
		if (distance < 5 && interval < 1)
		{
			mouseEvent.reset(Event_MouseClick);
			mouseEvent.setPos(mouseEvent.absolutePos() - focusWidget->absolutePos());
			widget_member(focusWidget)->procEvent(mouseEvent);
			if (mouse_click_time > 0.000001)
			{
				int distance = (mouseEvent.absolutePos() - mouse_click_pos).length();
				BReal interval = mouseEvent.time() - mouse_click_time;
				if (distance < 4 && interval < 1)
				{
					mouseEvent.reset(Event_DoubleClick);
					mouseEvent.setPos(mouseEvent.absolutePos() - focusWidget->globalPos());
					widget_member(focusWidget)->procEvent(mouseEvent);
					mouse_click_time = 0.0;
					mouse_click_pos = BPoint();
					return;
				}
			}
			else
			{
				mouse_click_time = mouseEvent.time();
				mouse_click_pos = mouseEvent.absolutePos();
			}
		}
		else
		{
			mouse_click_time = 0.0;
			mouse_click_pos = BPoint();
		}
	}
}
void member_BPixmap::procMouseMove(BMouseEvent& mouseEvent)
{
	if (focusWidget && mouse_pressed)
	{
		mouseEvent.setPos(mouseEvent.absolutePos() - focusWidget->absolutePos());
		widget_member(focusWidget)->procEvent(mouseEvent);
	}
	else
	{
		BPoint absolutePos = mouseEvent.absolutePos();
		BWidget* widget = widgetUnderPoint(absolutePos);
		if (hoverWidget != widget)
		{
			mouse_click_time = 0;
			BWidget* aboveWidget = widget;
			if (widget && widget_member(widget)->state.enabled)
			{
				BMouseEvent enterEvent = mouseEvent;
				enterEvent.reset(Event_MouseEnter);
				enterEvent.setPos(mouseEvent.absolutePos() - widget->globalPos());
				widget_member(widget)->procEvent(enterEvent);

				BEvent hoverEvent(Event_Hover, true);
				while (aboveWidget && !widget_member(aboveWidget)->state.hovered)
				{
					widget_member(aboveWidget)->state.hovered = true;
					widget_member(aboveWidget)->procEvent(hoverEvent);
					aboveWidget = widget_member(aboveWidget)->parent;
				}
			}
			if (hoverWidget && widget_member(hoverWidget)->state.enabled)
			{
				BMouseEvent leaveEvent = mouseEvent;
				leaveEvent.setType(Event_MouseLeave);
				leaveEvent.setPos(mouseEvent.absolutePos() - hoverWidget->globalPos());
				widget_member(hoverWidget)->procEvent(leaveEvent);

				BEvent hoverEvent(Event_Hover, false);
				while (hoverWidget && aboveWidget != hoverWidget)
				{
					widget_member(hoverWidget)->state.hovered = false;
					widget_member(hoverWidget)->procEvent(hoverEvent);
					hoverWidget = widget_member(hoverWidget)->parent;
				}
			}
			hoverWidget = widget;
		}
		tipsBoard.reset(widget);
		tipsBoard.pos = absolutePos;
		if (hoverWidget && widget_member(hoverWidget)->state.enabled)
		{
			mouseEvent.setPos(mouseEvent.absolutePos() - hoverWidget->globalPos());
			widget_member(hoverWidget)->procEvent(mouseEvent);
		}
	}
	BCursor* cursor = hoverWidget ? hoverWidget->cursor() : 0;
	if (hoverCursor != cursor)
	{
		hoverCursor = cursor;
		refresh = true;
	}
	if (hoverCursor && hoverCursor->type() == Cursor_None)
	{
		refresh = true;
	}
	freshCursor();
}
void member_BPixmap::procMouseWheel(BMouseEvent& mouseEvent)
{
	if (focusWidget && focusWidget->enabled())
	{
		widget_member(focusWidget)->procEvent(mouseEvent);
	}
}
void member_BPixmap::procDragMove(BMouseEvent& mouseEvent)
{
	drag = mouseEvent.value();
	BPoint absolutePos = mouseEvent.absolutePos();
	BWidget* widget = widgetUnderPoint(absolutePos);
	if (hoverWidget != widget)
	{
		widget->fresh();
		mouse_click_time = 0;
		if (hoverWidget)
		{
			//mouseEvent.setCursor(0);
			mouseEvent.reset(Event_DragLeave);
			mouseEvent.setPos(mouseEvent.absolutePos() - hoverWidget->absolutePos());
			widget_member(hoverWidget)->procEvent(mouseEvent);
		}
		if (widget && widget->enabled())
		{
			//mouseEvent.setCursor(0);
			mouseEvent.reset(Event_DragEnter);
			mouseEvent.setPos(mouseEvent.absolutePos() - widget->absolutePos());
			widget_member(widget)->procEvent(mouseEvent);
		}
		hover(widget);
	}
	if (hoverWidget && hoverWidget->enabled())
	{
		mouseEvent.reset(Event_DragMove);
		mouseEvent.setPos(mouseEvent.absolutePos() - hoverWidget->absolutePos());
		widget_member(hoverWidget)->procEvent(mouseEvent);
	}
}
void member_BPixmap::procDragDrop(BMouseEvent& mouseEvent)
{
	widget_member(hoverWidget)->procEvent(mouseEvent);
	drag = 0;
}

void member_BPixmap::slotImageDirty()
{

}
void member_BPixmap::slotWidgetFramed()
{

}

